package com.neulogistics.contrib.procuredcenter.api.application.command.handler;

import com.blackto.lib.mediat.unicast.IRequestHandler;
import com.neulogistics.contrib.procuredcenter.api.application.command.CreatePurchaseOrderCommand;
import com.neulogistics.contrib.procuredcenter.api.application.integrationevent.IProcuredCenterIntegrationEventService;
import com.neulogistics.contrib.procuredcenter.api.application.integrationevent.publish.PurchaseOrderCreatedIntegrationEvent;
import com.neulogistics.contrib.procuredcenter.api.service.ThreadLocalService;
import com.neulogistics.contrib.procuredcenter.domain.model.aggregate.PurchaseOrder;
import com.neulogistics.contrib.procuredcenter.domain.model.enumeration.PurchaseType;
import com.neulogistics.contrib.procuredcenter.domain.repository.IGoodsRepository;
import com.neulogistics.contrib.procuredcenter.domain.repository.IPurchaseOrderRepository;
import com.neulogistics.contrib.procuredcenter.domain.repository.IVendorRepository;
import com.neulogistics.infrastructure.cache.idservice.RedisIdUtil;
import com.neulogistics.infrastructure.common.annotation.ProduceEvent;
import com.neulogistics.infrastructure.common.serviceresult.BaseResponse;
import com.neulogistics.infrastructure.common.serviceresult.ResultUtils;
import com.neulogistics.infrastructure.integrationeventlog.model.IntegrationEventConstant;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;

@Component
public class CreatePurchaseOrderCommandHandler implements IRequestHandler<CreatePurchaseOrderCommand, BaseResponse<String>> {
    @Resource
    IPurchaseOrderRepository purchaseOrderRepository;

    @Resource
    RedisIdUtil redisIdUtil;

    @Resource
    TransactionTemplate transactionTemplate;

    @Resource
    IProcuredCenterIntegrationEventService procuredCenterIntegrationEventService;

    private final String PurchaseOrder_Id_Key;

    public CreatePurchaseOrderCommandHandler(@Value("${spring.application.name}") String appName) {
        PurchaseOrder_Id_Key = appName + ":" + "PurchaseOrderId";
    }

    @Override
    @ProduceEvent
    public BaseResponse<String> handle(CreatePurchaseOrderCommand command) throws Exception {
        // 生成id
        Long purchaseOrderId = redisIdUtil.nextId(PurchaseOrder_Id_Key);

        // 生成采购单
        PurchaseOrder purchaseOrder = new PurchaseOrder(purchaseOrderId, PurchaseType.Purchase,
                command.warehouseId, command.purchaseItem);

        // 开启事务，保存库存和出库单状态，发布事件
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
            try {
                // 持久化
                purchaseOrderRepository.save(purchaseOrder);

                // 生成采购事件
                Long eventId = redisIdUtil.nextId(IntegrationEventConstant.Integration_Event_Id_Key);
                PurchaseOrderCreatedIntegrationEvent purchaseOrderCreatedIntegrationEvent =
                        new PurchaseOrderCreatedIntegrationEvent(eventId, command.warehouseId, command.purchaseItem);
                Long transactionId = ThreadLocalService.transactionId.get();
                procuredCenterIntegrationEventService.addAndSaveEvent(purchaseOrderCreatedIntegrationEvent, transactionId);

            } catch (Exception e){
                // 触发回滚
                throw new RuntimeException(e.getCause().getMessage());
            }
            }
        });

        return ResultUtils.success(purchaseOrderId.toString());
    }
}
